/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package net.jueb.sniff4j.socksCroe;
import net.jueb.sniff4j.extr.base.AbstractRuntime;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.oio.OioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.oio.OioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

public final class SocksServer {
	protected static final InternalLogger log = InternalLoggerFactory.getInstance(SocksServer.class);
	private EventLoopGroup bossGroup;
	private EventLoopGroup workerGroup;
	private ServerBootstrap b;
	private Channel channel;
	public boolean isRun;

	public void run(AbstractRuntime runtime)
	{
		runByNiomode(runtime);
	}
	public void runByOiomode(AbstractRuntime runtime)
	{
		if(runtime==null)
		{
			return ;
		}
		String ip=runtime.getBootConfig().getProxyServerIp();//TODO
		int port=runtime.getBootConfig().getProxyServerPort();
        bossGroup = new OioEventLoopGroup();//主线程池
        workerGroup = new OioEventLoopGroup();//从线程池
        b = new ServerBootstrap();
        /**
         * 一个 ServerBootstrap 启动后，会创建一个 parent channel，
         * 这个 parent channel 用于接受 connections，
         * 每个 connection 会被分配到一个 child channel 上，用于后续的处理。
         */
        //初始化全局context，可以在每个连接的管道中使用以下方法获取
        runtime.bindServer(b);//TODO
        b.group(bossGroup, workerGroup);
        b.channel(OioServerSocketChannel.class);
        b.option(ChannelOption.SO_BACKLOG, 1024);//设置保持连接
        b.option(ChannelOption.SO_KEEPALIVE, true);//设置保持连接
        b.handler(new LoggingHandler(LogLevel.DEBUG));
        b.childHandler(new SocksServerInitializer());
        try {
        	//TODO 
        	if(ip==null)
        	{
        		channel=b.bind(port).sync().channel();
        	}else
        	{
        		channel=b.bind(ip,port).sync().channel();
        	}
			isRun=true;
		} catch (InterruptedException e) {
			isRun=false;
			e.printStackTrace();
		}
        new Thread(){
        	@Override
			public void run() {
        		try {
        			log.info("代理服务器Oio模式启动成功,地址："+channel.localAddress().toString());
                	channel.closeFuture().sync();
                	isRun=false;
                	log.info("代理服务器关闭!");
        		} catch (InterruptedException e) {
        			e.printStackTrace();
        		} finally {
                	//如果出现错误，则关闭主从线程池
                    bossGroup.shutdownGracefully();
                    workerGroup.shutdownGracefully();
                    isRun=false;
                }
        	};
        }.start();
	}
	public void runByNiomode(AbstractRuntime runtime)
	{
		if(runtime==null)
		{
			return ;
		}
		String ip=runtime.getBootConfig().getProxyServerIp();//TODO
		int port=runtime.getBootConfig().getProxyServerPort();
        bossGroup = new NioEventLoopGroup();//主线程池
        workerGroup = new NioEventLoopGroup();//从线程池
        b = new ServerBootstrap();
        /**
         * 一个 ServerBootstrap 启动后，会创建一个 parent channel，
         * 这个 parent channel 用于接受 connections，
         * 每个 connection 会被分配到一个 child channel 上，用于后续的处理。
         */
        //初始化全局context，可以在每个连接的管道中使用以下方法获取
        runtime.bindServer(b);//TODO
        b.group(bossGroup, workerGroup);
        b.channel(NioServerSocketChannel.class);
        b.option(ChannelOption.SO_BACKLOG, 1024);//设置保持连接
        b.option(ChannelOption.SO_KEEPALIVE, true);//设置保持连接
        b.childHandler(new SocksServerInitializer());
        try {
        	//TODO 
        	if(ip==null)
        	{
        		channel=b.bind(port).sync().channel();
        	}else
        	{
        		channel=b.bind(ip,port).sync().channel();
        	}
			isRun=true;
		} catch (InterruptedException e) {
			isRun=false;
			e.printStackTrace();
		}
        new Thread(){
        	@Override
			public void run() {
        		try {
        			log.info("代理服务器Nio模式启动成功,地址："+channel.localAddress().toString());
                	channel.closeFuture().sync();
                	isRun=false;
                	log.info("代理服务器关闭!");
        		} catch (InterruptedException e) {
        			e.printStackTrace();
        		} finally {
                	//如果出现错误，则关闭主从线程池
                    bossGroup.shutdownGracefully();
                    workerGroup.shutdownGracefully();
                    isRun=false;
                }
        	};
        }.start();
	}
	
    public void stop()
    {
    	if(isRun=false)
    	{
    		return;
    	}
    	try {
    		channel.close();
		} catch (Exception e) {
			// TODO: handle exception
		}
    	try {
			bossGroup.shutdownGracefully();
		} catch (Exception e) {
			// TODO: handle exception
		}
    	try {
    		workerGroup.shutdownGracefully();
		} catch (Exception e) {
			// TODO: handle exception
		}
    }
    
}
